<?php
// +----------------------------------------------------------------------
// | Buddy Framework 
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://buddy.woshimaijia.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: xinqiyang <xinqiyang@gmail.com>
// +----------------------------------------------------------------------


/**
 * validate forms
 * $_GET,$_POST
 * //get the functions
 *  $v = Validate::validate();
 *  if(isset($v['ajax'] == 1))
 *  {
 *  	$this->ajaxReturn($v['data'],$v['info'],$v['status'],$v['type']);
 *  }
 *  //if is the complex functions then set
 *
 * @author xinqiyang
 *
 */
class Validate
{

	public static function regex($value, $rule) {
		$validate = array(
            'require' => '/.+/',
            'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
            'url' => '/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/',
            'currency' => '/^\d+(\.\d+)?$/',
            'number' => '/^\d+$/',
            'zip' => '/^[1-9]\d{5}$/',
            'integer' => '/^[-\+]?\d+$/',
            'double' => '/^[-\+]?\d+(\.\d+)?$/',
            'english' => '/^[A-Za-z]+$/',
		);
		if (isset($validate[strtolower($rule)]))
		$rule = $validate[strtolower($rule)];
		return preg_match($rule, $value) === 1;
	}

	public static function autoCheckToken() {
		//token check lable
		if(C('token.'.APP_NAME)){
			return true;
		}
		$name = C('TOKEN_NAME');
		if (isset($_SESSION[$name])) {
			if (empty($_POST[$name]) || $_SESSION[$name] != $_POST[$name]) {
				return false;
			}
			unset($_POST[$name]);
			unset($_SESSION[$name]);
		}
		return true;
	}

	/**
	 * validate
	 * get the result data from request
	 */
	public static function validates()
	{
		$r = array('data'=>'','info'=>'Bad Request','status'=>'1','type'=>'json');
		$action = MODULE_NAME.':'.ACTION_NAME;
		//var_dump($action);die;
		if($_SERVER['REQUEST_METHOD'] === 'GET')
		{
			$head = C(strtolower(APP_NAME).':head');
			if(!empty($head) && in_array($action,array_keys($head)))
			{
				//$params = array();
				$params = C(strtolower(APP_NAME).':data.'.$action);
				//@TODO:get param to get the data  and judge the permission
				if(isset($params['params'])){
					//@TODO: DO RUN THE LIBRARY FUNCTIONS 
					$params['params'] = self::prepareParams($params['params']);
				}
				if(isset($params['resource'])){
					$dataReturn = call_user_func_array($params['resource'], array($params['params']));
					//DO REQUEST AND GET
					$r = array('data'=>array('data'=>$dataReturn),'info'=>'','status'=>'0','type'=>'json');
				}else{
					$r = array('data'=>'','info'=>'','status'=>'1','type'=>'json');
				}
			}
			
		} elseif($_SERVER['REQUEST_METHOD'] === 'POST') {
			if(!empty($_POST['form'])) // && strtolower(MODULE_NAME) == 'post'
			{
				//get the form of the website
				if(in_array($_POST['form'],array_keys(C(APP_NAME.'Forms'))))
				{
					logTrace(__CLASS__.'/'.__FUNCTION__.': validate post not empty '.implode(',', $_POST));
					//check token first
					//@TODO: useraction no check form token
					if(!self::autoCheckToken())
					{
						//check and die
						die(json_encode(array('data'=>'','info'=>'Please reflash Page then Post!','status'=>'1','type'=>'json')));
					}
					
					//get validate result
					$r = self::_doValidate();
					//var_dump($r);die;
					
				}
			}
			logTrace(__CLASS__.'/'.__FUNCTION__.': validate post '.implode(',', $_POST));
		}
		//var_dump($r);
		return $r;
	}
	//do validate of the deal
	public static function _doValidate($data = '')
	{
		//get $_POST then do validate and auto then return an array
		//status 0 success   1 error  3  redirect  4   //redirect do by js
		$return = array('data'=>'','info'=>'','status'=>'0','type'=>'json');

		if(empty($data)) {
			$data = $_POST;
		}elseif(is_object($data)){
			$data = get_object_vars($data);
		}elseif(!is_array($data)){
			$return['info'] = 'DATA_TYPE_INVAILD';
			$return['status'] = 1;
			return $return;
		}
		
		logTrace(__CLASS__.'/'.__FUNCTION__.':show post data         '.implode(',', $data));
		//map the filed ,get the target fields
		$check = C(APP_NAME.'FORMS');
		$checkform = $check[$_POST['form']]; //get form validate filed configuration
		//logDebug($_POST['form'].":".json_encode($checkform));
		$validateField = $checkform['check'];
		$r = true;
		//return the result data
		$vo = array();
		if(!empty($checkform['fields']))
		{
			foreach ($checkform['fields'] as $key=>$val)
			{
				if(isset($data[$key]))
				{
					$vo[$val] = $data[$key];
				}else{
					//merge the form value
					if(isset($checkform['value'][$val])){
						$vo[$val] = $checkform['value'][$val];
					}else{
						$vo[$val] = '';
					}
				}
			}
		}

		logTrace(__CLASS__.'/'.__FUNCTION__.':do check field ok'.implode(',', $vo));
		//do validate
		if(!empty($validateField) && !empty($vo))
		{
			foreach ($validateField as $key=>$val)
			{
				switch($val[0])
				{
					case 1:
						$do = self::regex($vo[$key], $val[1]);
						if($do !== $r)
						{
							$return['info'] = $val[2];
							$return['status'] = 1;
							//if get error then what will do ?
							if($checkform['return'] == 'json')
							{
								header("Content-Type:text/html; charset=utf-8");
								exit(json_encode($return));
							}else{
								header("Content-Type:text/xml; charset=utf-8");
            					exit(xml_encode($return));
							}
						}
						break;
					case 2:
						if(!empty($vo[$key]))
						{
							$do = self::regex($vo[$key], $val[1]);
							if($do !== $r)
							{
								$return['info'] = $val[2];
								$return['status'] = 1;
								if($checkform['return'] == 'json')
								{
									header("Content-Type:text/html; charset=utf-8");
									exit(json_encode($return));
								}elseif($checkform['return'] == 'xml'){
									header("Content-Type:text/xml; charset=utf-8");
            						exit(xml_encode($return));
								}
							}
						}
				}

			}
		}
		logTrace(__CLASS__.'/'.__FUNCTION__.': do validate ok '.implode(',', $vo));
		//do auto
		$auto = $checkform['auto'];
		if(!empty($auto))
		{
			foreach ($auto as $key=>$val)
			{
				$str = '';
				switch ($val)
				{
					case 'objid':
						$str = objid();
						break;
					case 'md5':
						if(!empty($_POST[$key])){
							$str = md5($_POST[$key]);
						}
						break;
					case 'time':
						$str = time();
						break;
					case 'getip':
						$str = getip();
						break;
					case 'userid':
						$str = userID();
						break;
					/*
					case 'post':
						$str = $_POST[''];
						break;
					case 'get':
						$str = $_POST[''];
						break;
					*/
					
				}
				
				$vo[$key] = $str;
			}
		}
		
		logTrace(__CLASS__.'/'.__FUNCTION__.': do auto ok  '.implode(',', $vo));
		$r = call_user_func_array($checkform['api'], array($vo));
		//var_dump($r);die;
		if(!$r)
		{
			$return['status'] = '1';
			$return['info'] = 'sys error,please waite';
			$return['data'] = '';
			$return['type'] = 'json';
			//@TODO : if error then do
			if(!$checkform['ajax']){
				jump(U('Public/404'));
			}else{
				header("Content-Type:text/html; charset=utf-8");
				exit(json_encode($return));
			}
		}else{
			//set session
			logTrace(__CLASS__.'/'.__FUNCTION__.':'.implode(',', $vo));
			//@TODO ： NEED CHANGE 
			if(isset($checkform['callback'])){
				//set session
				$method = $checkform['callback'];
				AccountService::setSession(${$method}['id']);
			}
			//redirect to the page
			if(!$checkform['ajax'] && isset($checkform['next'])){
				jump(U($checkform['next']));
			}
		}
		return $return;
	}


	public static function doWork($url,$params)
	{
		//GET API SERVER THEN DO WORK
		$url = C('InputURL').$url;
		//define the request method
		$method = $params['method'];
		unset($params['method']);
		logDebug(__CLASS__.'/'.__FUNCTION__.": method $method  url:$url params:".implode(',', $params));
		$r = Curl::$method($url, $params);
		//what data type is api server return ? json or the string?
		logDebug(__CLASS__.'/'.__FUNCTION__.': do work post result '.$r);
		return $r;
	}
	
	public static function getApiData($params)
	{
		//GET API SERVER THEN DO WORK
		//@TODO: Output URL should use more than one machine
		$url = C('OutputURL');
		if(!empty($params))
		{
			$url .= $params;
			logNotice(__CLASS__.'/'.__FUNCTION__.':'.$url);
			return Curl::get($url);
		}
	}
	
	/**
	 * do prepare params from the url
	 * Enter description here ...
	 * @param unknown_type $params
	 */
	public static function prepareParams($params)
	{
		//@TODO extend param of the url
		$array = array(':id',':o',':uid',':limit',':type',':enname');
		if(!empty($params)){
				foreach ($array as $key=>$val)
				{
					$getval = ltrim($val,':');
					if(isset($_GET[$getval]))
					{
						$params = str_replace($val, $_GET[$getval], $params);
					}
					if($getval === 'uid'){
						$params = str_replace($val, userID(), $params);
					}
				}
			
		}
		return $params;
	}

	
	/**
	 * do prepare params from the url
	 * Enter description here ...
	 * @param unknown_type $params
	 */
	public static function prepareInputParams($params)
	{
		//@TODO extend param of the url
		$array = array(':id',':o',':uid',':limit',':type');
		if(!empty($params)){
			
				foreach ($array as $val)
				{
					$getval = ltrim($val,':');
					if(isset($_POST[$getval]) && intval($_POST[$getval]))
					{
						$params = str_replace($val, $_POST[$getval], $params);
					}
					if($getval === 'uid'){
						$params = str_replace($val, userID(), $params);
					}
				}
			
		}
		return $params;
	}

	
}
